/*
 *    Comparer.java
 *    Copyright (C) 2007 David Milne, d.n.milne@gmail.com
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package org.wikipedia.miner.service;

import org.w3c.dom.*;

import org.wikipedia.miner.model.*;
import org.wikipedia.miner.util.*;
import org.wikipedia.miner.util.text.*;


/**
 * This service measures the semantic relatedness between terms.
 * 
 *  @author Stephen Remde
 */
public class MassCompare {

	private WikipediaMinerServlet wms ;
	
	private boolean defaultShowDetails = false ;
	private int defaultMaxLinkCount = 250 ;

	/**
	 * Initializes a new Comparer
	 * @param wms the servlet that hosts this service
	 */
	public MassCompare(WikipediaMinerServlet wms) {
		this.wms = wms;
	}
	
	/**
	 * @return false: the default behavior is to not show details of how terms are compared. 
	 */
	public boolean getDefaultShowDetails() {
		return defaultShowDetails ;
	}
	
	/**
	 * @return the default maximum number of links that are shown when providing details of how terms are compared.
	 */
	public int getDefaultMaxLinkCount() {
		return defaultMaxLinkCount ;
	}
	
	/**
	 * @return an Element description of this service; what it does, and what parameters it takes.
	 */
	public Element getDescription() {
		
		Element description = wms.doc.createElement("Description") ;
		description.setAttribute("task", "masscompare") ;
		
		description.appendChild(wms.createElement("Details", "<p>This service measures the semantic relatedness between two terms or a set of page ids. From this you can tell, for example, that New Zealand has more to do with <a href=\"" + wms.context.getInitParameter("service_name") + "?task=compare&details=true&term1=New Zealand&term2=Rugby\">Rugby</a> than <a href=\"" + wms.context.getInitParameter("service_name") + "?task=compare&details=true&term1=New Zealand&term2=Soccer\">Soccer</a>, or that Geeks are more into <a href=\"" + wms.context.getInitParameter("service_name") + "?task=compare&details=true&term1=Geek&term2=Computer Games\">Computer Games</a> than the <a href=\"" + wms.context.getInitParameter("service_name") + "?task=compare&details=true&term1=Geek&term2=Olympic Games\">Olympic Games</a> </p>"
				+ "<p>The relatedness measures are calculated from the links going into and out of each page. Links that are common to both pages are used as evidence that they are related, while links that are unique to one or the other indicate the opposite. The relatedness measure is symmetric, so comparing <i>a</i> to <i>b</i> is the same as comparing <i>b</i> to <i>a</i>. </p>" )) ;
		
		Element group1 = wms.doc.createElement("ParameterGroup") ;
		description.appendChild(group1) ;
		
		Element paramTerm1 = wms.doc.createElement("Parameter") ;
		paramTerm1.setAttribute("name", "term1") ;
		paramTerm1.appendChild(wms.doc.createTextNode( "The first of two terms (or phrases) to compare.")) ;
		group1.appendChild(paramTerm1) ;
		
		Element paramTerm2 = wms.doc.createElement("Parameter") ;
		paramTerm2.setAttribute("name", "term2") ;
		paramTerm2.appendChild(wms.doc.createTextNode( "A '|' seperated list of terms to compare to the first term.")) ;
		group1.appendChild(paramTerm2) ;
				
		return description ;
	}

	//TODO: add a method for comparing a set of article ids.
	
	/**
	 * Measures the relatedness between two terms, and 
	 * 
	 * @param term1 the first term to compare
	 * @param term2 the second term to compare
	 * @return an Element message of how the two terms relate to each other
	 * @throws Exception
	 */
	public Element getRelatedness(String term1, String term2) throws Exception {

		Element response = wms.doc.createElement("RelatednessResponses") ;
		
		if (term1 == null || term2 == null) {
			response.setAttribute("unspecifiedParameters", "true") ;
			return response ;
		}
				
		TextProcessor tp = new CaseFolder() ;

		Anchor anchor1 = new Anchor(term1, tp, wms.wikipedia.getDatabase()) ;
		SortedVector<Anchor.Sense> senses1 = anchor1.getSenses() ; 

		if (senses1.size() == 0) {
			response.setAttribute("unknownTerm", term1) ; 
			return response ;
		}

		String[] term2terms = term2.split("\\|");
		
		for (String term2a : term2terms)
		{
			Element response_ele = wms.doc.createElement("RelatednessResponse") ;
			response.appendChild(response_ele);
		
			Anchor anchor2 = new Anchor(term2a, tp, wms.wikipedia.getDatabase()) ;
			SortedVector<Anchor.Sense> senses2 = anchor2.getSenses() ; 
	
			if (senses2.size() == 0) {
				response_ele.setAttribute("unknownTerm", term2a) ; 
				
			}
			else				
			{
				response_ele.setAttribute("term1", term1) ;
				response_ele.setAttribute("term2", term2a) ;
	
				double sr = anchor1.getRelatednessTo(anchor2) ;
	
				response_ele.setAttribute("relatedness", wms.df.format(sr)) ;
			}			
		}
		
		return response;
		
	}
}
